#include <arch/arch.h>
#include <drivers/fdt/fdt_context.h>
#include <mm/mm.h>
static uintptr_t uart_base = 0;

static inline void mmio_write8(uintptr_t addr, uint8_t value) {
    *(volatile uint8_t *)addr = value;
}
int init_serial(void) { 
    if (!g_fdt_ctx.initialized) {
        printk("[UART] FDT not initialized, using default 0x10000000\n");
        uart_base = 0x10000000UL;
        return 0;
    }

    const void *fdt = g_fdt_ctx.fdt;
    int node = fdt_node_offset_by_compatible(fdt, -1, "ns16550a");
    if (node < 0) {
        printk("[UART] No compatible UART node found, using default 0x10000000\n");
        uart_base = 0x10000000UL;
        return 0;
    }

    int len;
    const fdt64_t *reg = fdt_getprop(fdt, node, "reg", &len);
    if (!reg || len < 16) {
        printk("[UART] Invalid 'reg' property, fallback to default\n");
        uart_base = 0x10000000UL;
        return 0;
    }

    uart_base = fdt64_to_cpu(reg[0]);
    uint64_t size = fdt64_to_cpu(reg[1]);

    // printk("[UART] Found UART base=0x%lx size=0x%lx (compatible=ns16550a)\n", uart_base, size);
    map_page_range(
        get_current_page_dir(),
        uart_base,
        uart_base,
        size, // 映射一整页
        PT_FLAG_R | PT_FLAG_W
    );

    *(volatile uint8_t *)(uart_base) = 's';
    *(volatile uint8_t *)(uart_base) = 'e';
    *(volatile uint8_t *)(uart_base) = 'r';
    *(volatile uint8_t *)(uart_base) = 'i';
    *(volatile uint8_t *)(uart_base) = 'a';
    *(volatile uint8_t *)(uart_base) = 'l';
    *(volatile uint8_t *)(uart_base) = '_';
    *(volatile uint8_t *)(uart_base) = 'o';
    *(volatile uint8_t *)(uart_base) = 'k';
    *(volatile uint8_t *)(uart_base) = '!';
    *(volatile uint8_t *)(uart_base) = '\n';
    
    return 0;
}

char read_serial() { return 0; }

void write_serial(char a) {
    if (!uart_base) return;
    mmio_write8(uart_base + 0x00, (uint8_t)a);
}
// void write_serial(char a) {}

void serial_printk(char *buf, int len) {
    for (int i = 0; i < len; i++) {
        if (buf[i] == '\n')
            write_serial('\r');
        write_serial(buf[i]);
    }
}
